package geneComponent;

import base.Parameter; 
import java.util.Random;

public class NodeFactory {
	
	
	public static Node getRandomNode(int maxDepth, int depth, int arity) {
		
		if(depth ==0){
			Parameter params = createFunctionParams(maxDepth, depth, arity);
			Node tempFunction = getFunction(params);
			
			return tempFunction; 
		}
		
		else if(new Random().nextInt(10)>5){
			 // 만약 50% 이상의 확률로 숫자가 나오면 터미널을 가짐 
			 Parameter params = createTerminalParams(maxDepth, depth,arity);
				return new Terminal(params); 
		 }
		
		 else if(maxDepth == depth) {
			 // maxDepth와 depth가 같으면 terminal을 가짐 
			Parameter params = createTerminalParams(maxDepth, depth,arity);
			return new Terminal(params); 
		 } 
		 else  {
			// 아니면 function을 가짐   
			Parameter params = createFunctionParams(maxDepth, depth, arity);
			return getFunction(params); 
		}
	}
	
	public static Node getRootNode(int maxDepth, int depth,int arity) {
		
		if(depth ==0){
			Parameter params = createFunctionParams(maxDepth, depth, arity);
			return getFunction(params); 
		}
		else if(new Random().nextInt(10)>5){
			 // 만약 50% 이상의 확률로 숫자가 나오면 터미널을 가짐 
			 Parameter params = createTerminalParams(maxDepth, depth,arity);
				return new Terminal(params); 
		 }
		 else if(maxDepth == depth) {
			 // maxDepth와 depth가 같으면 terminal을 가짐 
			Parameter params = createTerminalParams(maxDepth, depth,arity);
			return new Terminal(params); 
		 } 
		 else  {
			// 아니면 function을 가짐   
			Parameter params = createFunctionParams(maxDepth, depth, arity);
			return getFunction(params); 
		}
	}
	
	private static Parameter createTerminalParams(int maxDepth, int depth, int arity) {
		Parameter params = new Parameter();
	
		params.addParameter(Parameter.TYPE_TERM_VALUE, getTerminal());
		
		params.addParameter(Parameter.TYPE_MAX_DEPTH, String.valueOf(maxDepth));
		params.addParameter(Parameter.TYPE_DEPTH, String.valueOf(depth));
		params.addParameter(Parameter.TYPE_ARITY, String.valueOf(arity));

		return params;
	}

	private static Parameter createFunctionParams(int maxDepth, int depth,  int arity) {
		
		Parameter params = new Parameter();
		
		params.addParameter(Parameter.TYPE_MAX_DEPTH, String.valueOf(maxDepth));
		params.addParameter(Parameter.TYPE_DEPTH, String.valueOf(depth));
		params.addParameter(Parameter.TYPE_ARITY, String.valueOf(arity));
		
		return params;
	}
	
	private static Node getFunction(Parameter params) {
		switch(1 + (int)(Math.random() * 4)){
		case 1:
			return new Add(params);
		case 2:
			return new Sub(params);
		case 3:
			return new Mul(params);
		case 4:
			return new Div(params);
		case 5:
			params.addParameter(Parameter.TYPE_ARITY, "1");
			return new Sqrt(params);
		}
		
		return new Add(params);
	}
	
	private static String getTerminal () {
		switch(1 + (int)(Math.random() * 3	)){
		case 1:
			return Parameter.TYPE_VALUE_CT;
		case 2:
			return Parameter.TYPE_VALUE_RM;
		case 3:
			return Parameter.TYPE_VALUE_PT;
		}
		
		return Parameter.TYPE_VALUE_PT;
	}
	
}
